package com.wwinsoft.oa.web.aftersales;

import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.engine.IdentityService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.apache.commons.lang.StringUtils;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.springframework.beans.factory.annotation.Autowired;

import com.wwinsoft.framework.entity.security.User;
import com.wwinsoft.framework.service.security.AccountManager;
import com.wwinsoft.framework.utils.JXLTHelper;
import com.wwinsoft.framework.web.CrudActionSupport;
import com.wwinsoft.framework.web.SimpleActionSupport;
import com.wwinsoft.modules.orm.Page;
import com.wwinsoft.modules.security.springsecurity.SpringSecurityUtils;
import com.wwinsoft.modules.utils.DateUtils;
import com.wwinsoft.oa.entity.aftersales.AftersalesMaintain;
import com.wwinsoft.oa.pojo.aftersales.AftersalesMaintainBean;
import com.wwinsoft.oa.service.aftersales.AftersalesService;

/**
 * @author: Tim.Chen
 * @since: 1.0
 */
@Namespace("/aftersales")
@Results({ @Result(name = SimpleActionSupport.RELOAD, location = "/workflow/task!inbox.action", type = "redirect") })
public class AftersalesAction extends CrudActionSupport<AftersalesMaintain> {


    @Override
    public String list() throws Exception {
        page = aftersalesService.searchAftersalesMaintain(page, filter);
        return SUCCESS;
    }

    public void listExp() throws Exception {
        List<AftersalesMaintainBean> aftersalesMaintains = aftersalesService.searchAftersalesMaintain(filter);
        exportExcel(aftersalesMaintains);
    }
    private void exportExcel(List<AftersalesMaintainBean> aftersalesMaintains) {
        Map<String, Object> beans = new HashMap<String, Object>();
        beans.put("dataList", aftersalesMaintains);
        String fileName = "售后维护列表";
        JXLTHelper.writeXLTtoResponse(beans, AFTERSALES_EXCEL_TEMPLATE, fileName);
    }
    @Override
    public void prepareInput() throws Exception {
        if (StringUtils.isNotEmpty(taskId)) {
            prepareWFModel();
        } else {
        prepareModel();
    }

    }

    @Override
    public String input() throws Exception {
        if (entity.getCreateId() == null) {
            String loginedUserName = SpringSecurityUtils.getCurrentUserName();
            User user = accountManager.findUserByLoginName(loginedUserName);
            entity.setCreateId(user.getId());
        }
        return INPUT;
    }

    public void prepareView() throws Exception {
        prepareModel();
    }
    public String view() throws Exception {
        return "view";
    }
    @Override
    public String save() throws Exception {
        String loginedUserName = SpringSecurityUtils.getCurrentUserName();
        User user = accountManager.findUserByLoginName(loginedUserName);
        entity.setCreateId(user.getId());
        entity.setCreateTime(new Date());
        entity.setStatus(AftersalesMaintain.STATUS_IN_PROGRESS);
        saveEntity();
        if (StringUtils.isEmpty(processInstanceId)) {
            Map<String, Object> variables = new HashMap<String, Object>();
            variables.put("subject", entity.getTitle());
            ProcessInstance processInstance = startWorkflow(String.valueOf(entity.getId()), variables);
            processInstanceId = processInstance.getProcessInstanceId();
            entity.setProcessInstanceId(processInstanceId);
            saveEntity();
        } else {
            runtimeService.setVariable(processInstanceId, "subject", entity.getTitle());
        }
        return INPUT;
    }

    public void prepareSubmit() throws Exception {
        prepareModel();
    }

    public String submit() throws Exception {
        save();
        if (StringUtils.isEmpty(taskId)) {
            Task currentTask = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
            taskId = currentTask.getId();
        }
        submitTask();
        return RELOAD;
    }

    public void prepareApproval() throws Exception {
        prepareWFModel();
    }

    public String approval() throws Exception {
        return "approval";
    }

    public String approveTask() {
        if (StringUtils.isNotEmpty(taskId)) {
            Map paraMap = Collections.singletonMap("aftersalesApproved", true);
            submitTask(paraMap);
        }
        return RELOAD;
    }

    public String rejectTask() {
        if (StringUtils.isNotEmpty(taskId)) {
            Map paraMap = Collections.singletonMap("aftersalesApproved", false);
            submitTask(paraMap);
        }
        return RELOAD;
    }

    public void prepareInputTimeline() throws Exception {
        prepareWFModel();
    }

    public String inputTimeline() throws Exception {
        return "inputTimeline";
    }

    public void prepareTimelineTask() throws Exception {
        prepareModel();
    }

    public String timelineTask() throws Exception {
        saveEntity();
        submitTask(entity.getExpectTime());
        return RELOAD;
    }

    public void prepareComplete() throws Exception {
        prepareWFModel();
    }

    public String complete() throws Exception {
        return "complete";
    }

    public void prepareCompleteTask() throws Exception {
        prepareModel();
    }

    public String completeTask() throws Exception {
        entity.setEndTime(new Date());
        saveEntity();
        submitTask();
        return RELOAD;
    }

    public void prepareGrade() throws Exception {
        prepareWFModel();
    }

    public String grade() throws Exception {
        return "grade";
    }

    public void prepareGradeTask() throws Exception {
        prepareModel();
    }

    public String gradeTask() throws Exception {
        saveEntity();
        submitTask();
        return RELOAD;

    }

    @Override
    public String delete() throws Exception {
        return null;
    }

    private void prepareWFModel() throws Exception {
        if (StringUtils.isNotEmpty(taskId)) {
            task = taskService.createTaskQuery().taskId(taskId).singleResult();
            ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                    .processInstanceId(task.getProcessInstanceId()).singleResult();
            processInstanceId = processInstance.getProcessInstanceId();
            entity = aftersalesService.getAftersalesMaintain(Long.valueOf(processInstance.getBusinessKey()));
        }
    }

    @Override
    protected void prepareModel() throws Exception {
        if (id != null) {
            entity = aftersalesService.getAftersalesMaintain(id);
            processInstanceId = entity.getProcessInstanceId();
        } else {
            entity = new AftersalesMaintain();
        }
    }

    private void saveEntity() {
        aftersalesService.saveAftersalesMaintain(entity);
    }
    @Override
    public AftersalesMaintain getModel() {
        return entity;
    }

    private ProcessInstance startWorkflow(String businessKey, Map variables) {
        ProcessInstance processInstance;
        try {
            identityService.setAuthenticatedUserId(SpringSecurityUtils.getCurrentUserName());
            processInstance = runtimeService.startProcessInstanceByKey(PROCESS_DEFINITION_KEY, businessKey, variables);
        } finally {
            identityService.setAuthenticatedUserId(null);
        }
        return processInstance;
    }

    private void submitTask() {
        addComment();
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("dateVariable", createNextTaskDueDate());
        taskService.complete(taskId,variables);
    }
    private void submitTask(Date dueDate) {
        addComment();
        Map<String, Object> variables = new HashMap<String, Object>();
        variables.put("dateVariable", dueDate);
        taskService.complete(taskId,variables);
    }
    private void submitTask(Map paraMap) {
        addComment();
        taskService.complete(taskId, paraMap);
    }
    private void addComment() {
        if (StringUtils.isEmpty(comment)) {
            return;
        }
        try {
            identityService.setAuthenticatedUserId(SpringSecurityUtils.getCurrentUserName());
            taskService.addComment(taskId, processInstanceId, comment);
        } finally {
            identityService.setAuthenticatedUserId(null);
        }
    }
    public List<Comment> getComments() {
        return taskService.getProcessInstanceComments(processInstanceId);
    }
    private Date createNextTaskDueDate(){
        return DateUtils.addDays(new Date(), 2);
    }
    @Autowired
    TaskService taskService;

    @Autowired
    RuntimeService runtimeService;

    @Autowired
    AftersalesService aftersalesService;

    @Autowired
    AccountManager accountManager;

    @Autowired
    IdentityService identityService;

    private String processInstanceId;
    private Long id;
    private AftersalesMaintain entity;
    private Page<AftersalesMaintainBean> page = new Page<AftersalesMaintainBean>();
    private Task task;
    private String taskId;
    private String comment;
    private AftersalesMaintainBean filter = new AftersalesMaintainBean();
    private static final String PROCESS_DEFINITION_KEY = "AfterSalesMaintenance";
    private static final String AFTERSALES_EXCEL_TEMPLATE = "/template/excel/Aftersales_Template.xls";

    public void setId(Long id) {
        this.id = id;
    }


    public String getTaskId() {
        return taskId;
    }

    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }

    public String getProcessInstanceId() {
        return processInstanceId;
    }

    public void setProcessInstanceId(String processInstanceId) {
        this.processInstanceId = processInstanceId;
    }

    public Task getTask() {
        return task;
    }

    public void setTask(Task task) {
        this.task = task;
    }

    public Page<AftersalesMaintainBean> getPage() {
        return page;
    }
    public String getComment() {
        return comment;
    }
    public void setComment(String comment) {
        this.comment = comment;
    }
    public AftersalesMaintainBean getFilter() {
        return filter;
    }
}